home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 11: TSX-11 / Linux Cubed Series 11 - TSX-11 Vol 1.iso / sbin / bootutil.1 / bootutil / bootutils / mount / sundries.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-01  |  7.0 KB  |  315 lines

  1. /* Our little helpers.  Exported functions are prototyped in sundries.h.
  2.  * $Header: /usr/src/mount/RCS/sundries.c,v 1.1 1992/09/06 13:30:53 root Exp root $
  3.  */
  4.  
  5. #include "sundries.h"
  6.  
  7.  
  8. /* File pointer for /etc/mtab.  */
  9. FILE *F_mtab;
  10.  
  11. /* File pointer for lock.  */
  12. FILE *F_lock;
  13.  
  14. /* File descriptor for lock.  Value tested in unlock_mtab() to remove race.  */
  15. int lock = -1;
  16.  
  17. /* String list constructor.  (car() and cdr() are defined in "sundries.h").  */
  18. string_list
  19. cons (char * const a, const string_list b)
  20. {
  21.   string_list p;
  22.  
  23.   p = xmalloc (sizeof *p);
  24.  
  25.   car (p) = a;
  26.   cdr (p) = b;
  27.   return p;
  28. }
  29.  
  30. void *
  31. xmalloc (size_t size)
  32. {
  33.   void *t;
  34.  
  35.   if (size == 0)
  36.     return NULL;
  37.  
  38.   t = malloc (size);
  39.   if (t == NULL)
  40.     die (2, "not enough memory");
  41.   
  42.   return t;
  43. }
  44.  
  45. char *
  46. xstrdup (const char *s)
  47. {
  48.   char *t;
  49.  
  50.   if (s == NULL)
  51.     return NULL;
  52.  
  53.   t = strdup (s);
  54.  
  55.   if (t == NULL)
  56.     die (2, "not enough memory");
  57.  
  58.   return t;
  59. }
  60.  
  61. /* Call this with SIG_BLOCK to block and SIG_UNBLOCK to unblock.  */
  62. void
  63. block_signals (int how)
  64. {
  65.   sigset_t sigs;
  66.  
  67.   sigfillset (&sigs);
  68.   sigprocmask (how, &sigs, (sigset_t *) 0);
  69. }
  70.  
  71.  
  72. /* Non-fatal error.  Print message and return.  */
  73. void
  74. error (const char *fmt, ...)
  75. {
  76.   va_list args;
  77.  
  78.   va_start (args, fmt);
  79.   vfprintf (stderr, fmt, args);
  80.   fprintf (stderr, "\n");
  81.   va_end (args);
  82. }
  83.  
  84. /* Fatal error.  Print message and exit.  */
  85. void volatile
  86. die (int err, const char *fmt, ...)
  87. {
  88.   va_list args;
  89.  
  90.   va_start (args, fmt);
  91.   vfprintf (stderr, fmt, args);
  92.   fprintf (stderr, "\n");
  93.   va_end (args);
  94.  
  95.   exit (err);
  96. }
  97.  
  98. /* Ensure that the lock is released if we are interrupted.  */
  99. static void volatile
  100. handler (int sig)
  101. {
  102.   die (2, "%s", sys_siglist[sig]);
  103. }
  104.  
  105. /* Create the lock file.  The lock file will be removed if we catch a signal
  106.    or when we exit.  The value of lock is tested to remove the race.  */
  107. void
  108. lock_mtab (void)
  109. {
  110.   int sig = 0;
  111.   struct sigaction sa;
  112.  
  113.   /* If this is the first time, ensure that the lock will be removed.  */
  114.   if (lock < 0)
  115.     {
  116.       sa.sa_handler = handler;
  117.       sigfillset (&sa.sa_mask);
  118.   
  119.       /* We should use sigismember() but it is broken for libc <= 4.2.  */
  120. #if 0
  121.       while (sigismember (&sa.sa_mask, ++sig) != -1)
  122. #else
  123.       while (++sig < _NSIG)
  124. #endif
  125.     sigaction (sig, &sa, (struct sigaction *) 0);
  126.     }
  127.  
  128.   if ((lock = open (MOUNTED_LOCK, O_WRONLY|O_CREAT|O_EXCL, 0644)) < 0)
  129.     die (2, "can't create lock file %s: %s", MOUNTED_LOCK, strerror (errno));
  130.  
  131.   F_lock = fdopen (lock, "w");
  132. }
  133.  
  134. /* Remove lock file.  */
  135. void
  136. unlock_mtab (void)
  137. {
  138.   endmntent (F_lock);
  139.   if (lock != -1)
  140.     unlink (MOUNTED_LOCK);
  141. }
  142.  
  143.  
  144. /* Create mtab with a root entry.  */
  145. static void
  146. create_mtab (void)
  147. {
  148.   struct mntent *fstab;
  149.  
  150.   if ((F_mtab = setmntent (MOUNTED, "a+")) == NULL)
  151.     die (1, "mount: can't open %s for writing: %s", MOUNTED, strerror (errno));
  152.  
  153.   /* Find the root entry by looking it up in fstab, which might be wrong.
  154.      We could statfs "/" followed by a slew of stats on /dev/ but then
  155.      we'd have to unparse the mount options as well....  */
  156.   if ((fstab = getfsfile ("/")) || (fstab = getfsfile ("root")))
  157.     {
  158.       if (addmntent (F_mtab, fstab) == 1)
  159.     die (1, "mount: error writing %s: %s", MOUNTED, strerror (errno));
  160.     }
  161.   if (fchmod (fileno (F_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
  162.     die (1, "mount: error changing mode of %s: %s", MOUNTED, strerror (errno));
  163.   endmntent (F_mtab);
  164. }
  165.  
  166. /* Open mtab.  */
  167. void
  168. open_mtab (const char *mode)
  169. {
  170.   if (fopen (MOUNTED, "r") == NULL)
  171.     create_mtab ();
  172.   if ((F_mtab = setmntent (MOUNTED, mode)) == NULL)
  173.     die (2, "can't open %s: %s", MOUNTED, strerror (errno));
  174. }
  175.  
  176. /* Close mtab.  */
  177. void
  178. close_mtab (void)
  179. {
  180.   if (fchmod (fileno (F_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
  181.     die (1, "mount: error changing mode of %s: %s", MOUNTED, strerror (errno));
  182.   endmntent (F_mtab);
  183. }
  184.  
  185. /* Parse a -t typelist into a string list.  */
  186. string_list
  187. parse_types (char *types)
  188. {
  189.   string_list list;
  190.   char *t;
  191.  
  192.   if (types == NULL)
  193.     return NULL;
  194.  
  195.   list = cons (strtok (types, ","), NULL);
  196.  
  197.   while ((t = strtok (NULL, ",")) != NULL)
  198.     list = cons (t, list);
  199.  
  200.   return list;
  201. }
  202.  
  203. /* True if fstypes match.  Null *TYPES means match anything,
  204.    except that swap types always return false.  This routine
  205.    has some ugliness to deal with ``no'' types.  */
  206. int
  207. matching_type (const char *type, string_list types)
  208. {
  209.   char *notype;
  210.   int no;            /* true if a "no" type match, ie -t nominix */
  211.  
  212.   if (streq (type, MNTTYPE_SWAP))
  213.     return 0;
  214.   if (types == NULL)
  215.     return 1;
  216.  
  217.   if ((notype = alloca (strlen (type) + 3)) == NULL)
  218.     die (2, "mount: out of memory");
  219.   sprintf (notype, "no%s", type);
  220.   no = (car (types)[0] == 'n') && (car (types)[1] == 'o');
  221.  
  222.   /* If we get a match and the user specified a positive match type (e.g.
  223.      "minix") we return true.  If we match and a negative match type (e.g.
  224.      "nominix") was specified we return false.  */
  225.   while (types != NULL)
  226.     if (streq (type, car (types)))
  227.       return !no;
  228.     else if (streq (notype, car (types)))
  229.       return 0;            /* match with "nofoo" always returns false */
  230.     else
  231.       types = cdr (types);
  232.  
  233.   /* No matches, so if the user specified a positive match type return false,
  234.      if a negative match type was specified, return true.  */
  235.   return no;
  236. }
  237.  
  238. /* Make a canonical pathname from PATH.  Returns a freshly malloced string.
  239.    It is up the *caller* to ensure that the PATH is sensible.  i.e.
  240.    canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.''
  241.    is not a legal pathname for ``/dev/fd0.''  */
  242. char *
  243. canonicalize (const char *path)
  244. {
  245.   char *canonical = xmalloc (PATH_MAX + 1);
  246.   char *p = canonical;
  247.   
  248.   if (path == NULL)
  249.     return NULL;
  250.   
  251.   if (streq (path, "none"))
  252.     {
  253.       strcpy (canonical, path);
  254.       return canonical;
  255.     }
  256.   if (strchr (path, ':') != NULL)
  257.     {
  258.       strcpy(canonical, path);
  259.       return canonical;
  260.     }
  261.   if (*path == '/')
  262.     {
  263.       /* We've already got an absolute path in PATH, but we need at
  264.      least one char in canonical[] on entry to the loop below.  */
  265.       *p = *path++;
  266.     }
  267.   else
  268.     {
  269.       getcwd (canonical, PATH_MAX);
  270.       p = canonical + strlen (canonical) - 1;
  271.       if (*p != '/')
  272.     *++p = '/';
  273.     }
  274.   
  275.   /* There is at least one character in canonical[],
  276.      and the last char in canonical[], *p, is '/'.  */
  277.   while ((*path != '\0') && (p < canonical + PATH_MAX))
  278.     if (*p != '/')
  279.       {
  280.     *++p = *path++;
  281.       }
  282.     else
  283.       {
  284.     if (path[0] == '/')
  285.       {
  286.         path++;        /* eliminate duplicate slashes (``//'') */
  287.       }
  288.     else if ((path[0] == '.') && ((path[1] == '\0') || (path[1] == '/')))
  289.     {
  290.       path++;        /* eliminate ``/.'' */
  291.     }
  292.     else if ((path[0] == '.') && (path[1] == '.')
  293.          && ((path[2] == '\0') || (path[2] == '/')))
  294.       {
  295.         while ((p > canonical) && (*--p != '/'))
  296.           /* ascend on ``/../'' */
  297.           ;
  298.         path += 2;
  299.       }
  300.     else
  301.       {
  302.         *++p = *path++;    /* not a special case, just copy char */
  303.       }
  304.       }
  305.   if (p >= (canonical + PATH_MAX))
  306.     die (2, "mount: path too long");
  307.  
  308.   if (*p == '/')
  309.     --p;            /* eliminate trailing slash */
  310.  
  311.   *++p = '\0';
  312.   
  313.   return canonical;
  314. }
  315.